// salesContract.js
import { CsDouble } from '../common/csDouble.js';
import { CsFundDouble } from '../common/csFundDouble.js';
import { Definition } from '../common/definition.js';
import { DocBase } from '../common/docBase.js';
import { CommonOrderStatus, DocType, ProgressState } from '../common/docDefinition.js';
import { Engine } from '../engine.js';
import { FundAccount } from '../funds/fundAccount.js';
import { PendingReceiveOrder } from '../funds/pendingReceiveOrder.js';
import { PendingInventory } from '../inventory/pendingInventory.js';
import { WareHouse } from '../inventory/warehouse.js';
import { TargetObject, TargetObjectPlatformType, TargetObjectType } from '../targetOrg/targetObject.js';
import { Util } from '../../utils/util.js';
import { OrderUtil } from '../../utils/orderUtil.js';
import { CommodityBatchWithTax } from './sales.js';
import { FunctionPermissionDefinition } from '../platform/functionPermissionDefinition.js';
import { OrderSelfDefFundData } from '../funds/orderSelfDefFundData.js';
import { OrderOtherFundData } from '../funds/orderOtherFundData.js';
import {MetalSalesTradeMode} from '../common/metalDefinition.js';

/**
 * 销售合同/销售单
 */
export class SalesContract extends DocBase {

    /** @type {SalesContract|null} 编辑前的订单 */
    _orderBeforeEdit = null;

    /** @type {TargetObject} 供应商/客户 */
    _targetObject;

    /** @type {WareHouse} 仓库 */
    wareHouse;

    /** @type {Array<CommodityBatchWithTax>} 商品列表 */
    _commmodityList = [];

    /** @type {CsDouble} 商品数量 */
    _quantity;

    /** @type {CsFundDouble} 商品金额 */
    _commodityPrice;

    /** @type {CsFundDouble} 含税价 */
    _priceWithTax;

    /** @type {CsFundDouble} 其他费用 */
    _otherCost;

    /** @type {CsFundDouble} 优惠金额 */
    _discount;

    /** @type {CsFundDouble|null} 现结款 (单内) */
    _payedMount = null;

    /** @type {CsFundDouble}  应付余款 (单内) */
    _remainAmount;

    /** @type {CsFundDouble} 总计费用 */
    _totalMount;

    /** @type {PendingInventory|null} 出库信息 */
    inventory = null;

    /** @type {PendingReceiveOrder|null} 收款信息 */
    receiveOrder = null;

    /** @type {ProgressState} 支付状态 */
    receiveProgress = ProgressState.None;

    /** @type {ProgressState} 入库状态 */
    inventoryProgress = ProgressState.None;

    /** @type {CsDouble} 折扣比例(0-100) */
    _discountRatio;

    /** @type {boolean} 抹零 */
    _withoutSmallChange;

    /** @type {CsFundDouble} 抹零金额 */
    _smallChangeAmount;

    /** @type {CsFundDouble|null} 预收冲抵  为空则默认用于冲抵*/
    _preReceiveOffset = null;

    /** @type {boolean} 快速出库模式 */
    _quickInventoryMode;

    /** @type {boolean} 启用预收冲抵 */
    _enablePreReceiveOffset = false;

    /** @type {FundAccount} 收款账户 */
    fundAccount;

    /** @type {OrderSelfDefFundData} 贵金属资金账户 */
    _metalFundsPrice;

    /** @type {OrderOtherFundData} 其他费用, 支付费用增加 */
    _otherFundsMorePrice;

    /** @type {OrderOtherFundData} 其他费用，支付费用减少 */
    _otherFundsLessPrice;

    get metalFundsPrice() {
        return this._metalFundsPrice;
    }

    /// 商品数量 CsDouble
    get quantity() {
        return this._quantity;
    }

    /// 商品金额 CsFundDouble
    get commodityPrice() {
        return this._commodityPrice;
    }

    /// 含税金额 CsFundDouble
    get priceWithTax() {
        return this._priceWithTax;
    }

    /// 税额 CsFundDouble
    get tax() {
        return this._priceWithTax.sub(this._commodityPrice);
    }

    /// 是否支持含税详情
    get isSupportDetailWithTax() {
        return Engine.getOrgSettings().enableSalesWithTaxDetail || this.tax.value !== 0;
    }

    /// 整单折扣率 CsDouble
    get discountRatio() {
        return this._discountRatio;
    }

    set discountRatio(value) {
        this._discountRatio = new CsDouble(
            value.value,
            { precision: Definition.gConstDiscountRatePrecision }
        );
        this.calculatePriceAndQuantity();
    }

    /// 折扣比例小数，用于计算 CsDouble
    get discountRatioForCalc() {
        return this._discountRatio.div(new CsDouble(100));
    }

    /// 抹零 bool
    get withoutSmallChange() {
        return this._withoutSmallChange;
    }

    set withoutSmallChange(value) {
        this._withoutSmallChange = value;
        this.calculatePriceAndQuantity();
    }

    /// 其他费用 CsFundDouble
    get otherCost() {
        return this._otherCost;
    }

    set otherCost(value) {
        this._otherCost = value;
        this.calculatePriceAndQuantity();
    }

    get otherFundsMorePrice() {
        return this._otherFundsMorePrice;
    }

    get otherFundsLessPrice() {
        return this._otherFundsLessPrice;
    }

    /// 优惠金额 CsFundDouble
    get discount() {
        return this._discount;
    }

    set discount(value) {
        this._discount = value;
        this.calculatePriceAndQuantity();
    }

    /// 现结款 CsFundDouble
    get payedMount() {
        if (Engine.getOrgSettings().enableSalesFullPayment ||
            this.targetObject.platformType === TargetObjectPlatformType.TPlatformCreated) {
            // 零售客户返回收款全额
            return this._payedMount ?? this._totalMount.sub(this.preReceiveOffset);
        } else {
            return this._payedMount ?? new CsFundDouble(0);
        }
    }

    set payedMount(value) {
        this._payedMount = value;
        this.calculatePriceAndQuantity();
    }

    /**
 * 抹零
 * 将订单金额零头计算并填充到优惠金额实现抹零
 */
    setDiscountValueWithSmallChange() {
        console.log('setDiscountValueWithSmallChange');
        let value = this._priceWithTax.value * this.discountRatioForCalc.value
        value += this.otherCost.value;
        value += this._otherFundsMorePrice.value.value;
        value -= this._otherFundsLessPrice.value.value;

        let discountValue = value - Math.floor(value);

        this.discount = new CsFundDouble(discountValue);
        this.calculatePriceAndQuantity();
    }

    /// 实际收款 CsFundDouble
    totalPayedMount(editMode) {
        if (editMode || !this.receiveOrder || Util.isEmpty(this.receiveOrder.id)) {
            return new CsFundDouble(this._allHeXiaoAmount);
        } else {
            return new CsFundDouble(this.receiveOrder.payedMount);
        }
    }

    /// 单据内已核销金额 number
    get _allHeXiaoAmount() {
        let value = 0;
        value += this.preReceiveOffset.value;
        value += this.payedMount.value;
        return value;
    }

    /// 应付余款(单内) CsFundDouble
    get remainAmount() {
        return this._remainAmount;
    }

    /// 应付余款(多单核销后) number
    get remainAmountWithAllHeXiao() {
        if (this.receiveOrder && !Util.isEmpty(this.receiveOrder.id)) {
            // 已审核单据采用待收款单据获取多单核销金额
            return this.receiveOrder.pendingPayMount;
        } else {
            // 未审核单据只有本单核销金额
            return this._totalMount.value - this._allHeXiaoAmount;
        }
    }

    /// 总计费用 CsFundDouble
    get totalMount() {
        return this._totalMount;
    }

    /// 优惠金额（单内） CsFundDouble
    get totalDiscountAmount() {
        return this._priceWithTax.add(this._otherCost).sub(this._totalMount);
    }

    /// 是否支持收款金额设定 bool
    get isSupportPayedMountSetting() {
        return this.targetObject.platformType !== TargetObjectPlatformType.TPlatformCreated;
    }

    /** @type {boolean} 启用预收冲抵 */
    get enablePreReceiveOffset() { return this._enablePreReceiveOffset; }
    set enablePreReceiveOffset(value) {
        this._enablePreReceiveOffset = value;
        if (!value) {
            this._preReceiveOffset = null;
        }
        this.calculatePriceAndQuantity();
    }



    /// 直接出库模式 bool
    get quickInventoryMode() {
        return this._quickInventoryMode;
    }
    set quickInventoryMode(value) {
        this._quickInventoryMode = value;
    }

    /// 商品含税费用 CsFundDouble
    get commodityPriceWithTax() {
        return this._priceWithTax;
    }

    /// 抹零金额 Number
    get smallChangeAmount() { return this._smallChangeAmount.value; }

    /// 预收冲抵 未处理数据 原对象
    get preReceiveOffsetOriginal() { return this._preReceiveOffset; }

    /// 预收冲抵
    /// 已有冲抵，返回已有冲抵金额
    /// 未设置冲抵金额，查看是否开启冲抵开关
    /// 开启则按最大冲抵金额返回
    // CsFundDouble
    get preReceiveOffset() {
        if (this._preReceiveOffset != null) {
            return this._preReceiveOffset;
        } else {
            if (this._enablePreReceiveOffset) {
                /// 开启预收冲抵，返回最大冲抵金额
                let preReceiveAmount = this.customerPreRecieveAmount;
                return preReceiveAmount > this.totalMount.value
                    ? this.totalMount
                    : new CsFundDouble(preReceiveAmount);
            }
            return new CsFundDouble(0);
        }
    }

    /**
     * 获取客户可用预收冲抵金额
     * @returns {number}
     */
    get customerPreRecieveAmount() {
        if (this._orderBeforeEdit &&
            this._orderBeforeEdit.targetObject.id === this.targetObject.id &&
            this._orderBeforeEdit.status.code === CommonOrderStatus.Passed.code &&
            this._orderBeforeEdit.id === this.id) {
            // 已审核的单据编辑，对于相同的客户
            // 可用预收冲抵金额 = 往来单位可用预收冲抵金额 + 单据之前冲抵金额
            return (this.targetObject.fundAmount?.value || 0) +
                (this._orderBeforeEdit.preReceiveOffsetOriginal?.value || 0);
        }
        return this.targetObject?.fundAmount?.value || 0;
    }

    /**
     * 设置编辑前的订单
     * @param {SalesContract|null} value 
     */
    set orderBeforeEdit(value) {
        this._orderBeforeEdit = value;
    }

    /**
     * 获取/设置目标客户
     */
    get targetObject() {
        return this._targetObject;
    }

    set targetObject(value) {
        if (this._targetObject?.id !== value.id) {
            this._targetObject = value;
            // 切换客户重置预收冲抵
            this._preReceiveOffset = null;
        }

        if (value?.platformType === TargetObjectPlatformType.TPlatformCreated) {
            // 平台客户只能全款收款
            this._payedMount = null;
        }

        this.calculatePriceAndQuantity();
    }

    /**
     * 进入编辑模式
     */
    enterEditMode() {
        if (this.targetObject.platformType === TargetObjectPlatformType.TPlatformCreated) {
            // 平台客户只能全款收款
            this._payedMount = null;
        }
        this.calculatePriceAndQuantity();
    }

    // 其他getter/setter和计算方法...
    // (保持与Dart版本相同的业务逻辑)

    /**
     * 更新商品列表
     * @param {Array<CommodityBatchWithTax>} list 
     */
    updateCommodityList(list) {
        this._commmodityList = [...list];
        this.calculatePriceAndQuantity();
    }

    /**
     * 添加商品批次
     * @param {CommodityBatchWithTax} batch 
     */
    addCommodityBatch(batch) {
        this._commmodityList.push(batch);
        this.calculatePriceAndQuantity();
    }

    /**
     * 添加或更新商品批次
     * @param {CommodityBatchWithTax} batch 
     */
    addOrUpdateCommodityBatch(batch) {
        const existing = this._commmodityList.find(item => item.commodity.id === batch.commodity.id);
        if (existing) {
            existing.addCount(new CsDouble(1));
        } else {
            this._commmodityList.push(batch);
            // 增加0， 触发内部价格计算
            batch.addCount(new CsDouble(0)); // 触发价格计算
        }
        this.calculatePriceAndQuantity();
    }

    //商品列表
    get commmodityList() {
        return this._commmodityList;
    }

    /**
     *是否是多条记录
     * @param {CommodityBatchWithTax} batch 
     * @returns {boolean}
     */
    isMultiRecord(batch) {
        return this._commmodityList
            .filter(element => element.commodity.id === batch.commodity.id)
            .length > 1;
    }

    /**
     *更新batch
     * @param {CommodityBatchWithTax} batch 
     * @param {CommodityBatchWithTax} orgBatch 
     * @returns {boolean}
     */
    updateCommodityBatch(batch, orgBatch) {
        let ret = false;
        const index = this._commmodityList.indexOf(orgBatch);
        if (index >= 0) {
            this._commmodityList[index] = batch;
            ret = true;
        }
        this.calculatePriceAndQuantity();
        return ret;
    }

    /**
     * 清除商品  -- 目前自动化测试用
     */
    clearCommodityBatch() {
        this._commmodityList = [];
        this.calculatePriceAndQuantity();
    }

    /**
     * 删除batch
     * @param {CommodityBatchWithTax} batch 
     * @returns {boolean}
     */
    removeCommodityBatch(batch) {
        const index = this._commmodityList.indexOf(batch);
        const ret = index > -1;
        if (ret) {
            this._commmodityList.splice(index, 1);
        }
        this.calculatePriceAndQuantity();
        return ret;
    }

    /**
     * 判断整单优惠金额有效性
     * @returns {string|null} Error message if invalid, null if valid
     */
    validateDiscountAmount() {
        const maxDiscount = this.priceWithTax.value * this.discountRatioForCalc.value;
        if (this.discount.value > maxDiscount) {
            return `优惠金额大于折后金额 ${new CsFundDouble(maxDiscount).value}`;
        }
        return null;
    }

    /**
     * 判断整单金额有效性
     * 实际收款可能大于应收款，该验证不再需要
     * @returns {string|null} Error message if invalid, null if valid
     */
    /*
    validateTotalAmount() {
        if (this._remainAmount.value < 0 && this.preReceiveOffset.value > 0) {
            return `实收金额大于单据金额，请检查本次收款金额，该金额应该小于等于单据 (应收金额 - 预收冲抵金额)。即 (0.00-${Util.getFundString(this._totalMount.value - this.preReceiveOffset.value, { currencyCharector: false })})`;
        } else if (this._remainAmount.value < 0) {
            return "本次收款金额大于应收金额";
        }
        return null;
    }
    */

    checkTotalAmount() {
        if (this._remainAmount.value < 0 && this.preReceiveOffset.value > 0) {
            return `实收金额+预收冲抵金额 > 应收金额。超出金额为: ${Util.getFundString(-this._remainAmount.value)}, 超出部分将存入用户资金账户!`;
        } else if (this._remainAmount.value < 0) {
            return `本次收款金额大于应收金额。超出金额为: ${Util.getFundString(-this._remainAmount.value)}, 超出部分将存入用户资金账户!`;
        }
        return null;
    }

    /** 校验单据合法性 */
    validateOrder() {
        // 商品校验
        if (this._commmodityList.isEmpty) {
            return { errorMsg: "请选择商品!" };
        }
        // 判断商品数量

        // 商品数量校验 DML 2025-09-03 新增空商品列，可能有商品列表，但是没有商品
        let withoutCommodity = true;
        for (let comRrd of this._commmodityList) {
            if (comRrd.commodity && comRrd.count.value == 0) {

                return { errorMsg: "商品[" + comRrd.commodity?.name + "]数量为0, 请调整商品数量!" };
            }

            if (comRrd.commodity && comRrd.count.value > 0) {
                withoutCommodity = false;
            }
        }

        if (withoutCommodity) {
            return { errorMsg: "请选择商品!" };
        }

        // 优惠金额校验
        let disCountErrorMsg = this.validateDiscountAmount();
        if (disCountErrorMsg) {
            return { msgBoxConfirm: true, errorMsg: disCountErrorMsg }
        }

        // 收款金额校验
        let totalWarning = this.checkTotalAmount();
        if (totalWarning) {
            return {
                msgBoxConfirm: true,
                warningMsg: totalWarning
            }
        }

        return null;
    }

    /**
     * 判断是否可以编辑
     * @returns {string|null} Error message if not editable, null if editable
     */
    validateEditAble() {
        let hintCode = 0;

        if (this.inventory && this.inventory.inventoryInList.length > 0) {
            hintCode = 1;
        }

        if (this.receiveOrder && this.receiveOrder.hasUserReceiveOrder) {
            hintCode += 10;
        }

        switch (hintCode) {
            case 0:
                return null;
            case 1:
                return "销售单据有关联出库单据，请先删除关联出库单据!";
            case 10:
                return "销售单据有关联收款单据，请先删除关联收款单据!";
            case 11:
                return "销售单据有关联出库和收款单据，请先删除关联出库和收款单据!";
            default:
                return null;
        }
    }

        // 过去结算贵金属信息
        // 1  _commmodityList 中的记录 isMetalTradeBatch = true
        // 2 _commmodityList 中的记录 metalSalesTradeMode?.code === MetalSalesTradeMode.SettleMetal.code
        // 3 累计相同贵金属的折后重量
        // 返回列表字符串，commodity.commodity.standard + commodity.batchPriceWithDiscount.value
        getSettledMetalInfo() { 
            return this._commmodityList.filter(item => item.isMetalTradeBatch && item.metalSalesTradeMode?.code === MetalSalesTradeMode.SettleMetal.code).map(item => item.commodity.standard + item.countAfterDiscount.value + 'g').join(",");
        }
        
        // 是否包含结价内容
        get hasSettledMetal() { 
            return this._commmodityList.some(item => item.isMetalTradeBatch && item.metalSalesTradeMode?.code === MetalSalesTradeMode.SettleMetal.code);
        }

    /**
     * 计算价格和数量
     */
    calculatePriceAndQuantity() {
        this._commodityPrice = CsFundDouble.zero();
        this._quantity = CsDouble.zero();
        this._priceWithTax = CsFundDouble.zero();

        this._metalFundsPrice.clear();

        this._commmodityList.forEach(item => {
            this._quantity = this._quantity.add(item.count);

            if (item.isMetalTradeBatch) {
                this._metalFundsPrice.addCommodityBatch(item);
            }

            // 结价模式，价格计入总价
            if (item.isSettlePrice) {
                this._commodityPrice = this._commodityPrice.add(item.batchPriceWithDiscount);
                this._priceWithTax = this._priceWithTax.add(item.batchPriceWithTax);
            }
        });

        this._totalMount = new CsFundDouble(this._priceWithTax.value * this.discountRatioForCalc.value)
            .add(this._otherCost)
            .add(this._otherFundsMorePrice.value)
            .sub(this._otherFundsLessPrice.value)
            .sub(this._discount);

        const totalWithoutChange = this._withoutSmallChange
            ? new CsFundDouble(Math.floor(this._totalMount.value))
            : this._totalMount;

        this._smallChangeAmount = this._totalMount.sub(totalWithoutChange);
        this._totalMount = totalWithoutChange;

        this._remainAmount = this._totalMount.sub(this.payedMount).sub(this.preReceiveOffset);
    }

    /// 复制    
    resetForCopy({ removeParentAndSourceData = true } = {}) {
        super.resetForCopy({ removeParentAndSourceData: removeParentAndSourceData });
        // 清除商品列表id
        this._commmodityList.forEach(element => {
            element.id = "";
        });

        // 支付重置
        this._preReceiveOffset = null;
        this._payedMount = null;
        this._orderBeforeEdit = null;
        this._enablePreReceiveOffset = false;
    }

    /**
     * Check if user has read permission
     * @returns {boolean} 
     */
    static hasReadPermission() {
        return Engine.profile.permissionMgr.hasPermission([
            FunctionPermissionDefinition.P_SalesContract_Read,
            FunctionPermissionDefinition.P_SalesContract_Edit,
            FunctionPermissionDefinition.P_SalesContract_Audit
        ]);
    }
    /**
 * Check if user has edit permission
 * @returns {boolean}
 */
    static hasEditPermission() {
        if (Engine.getOrgSettings().enableSalesRelatedOrdersQuickMode) {
            // 快捷模式下，编辑和审核同等权利
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_SalesContract_Edit,
                FunctionPermissionDefinition.P_SalesContract_Audit
            ]);
        } else {
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_SalesContract_Edit
            ]);
        }
    }

    /**
     * Check if user has audit permission 
     * @returns {boolean}
     */
    static hasAuditPermission() {
        if (Engine.getOrgSettings().enableSalesRelatedOrdersQuickMode) {
            // 快捷模式下，编辑和审核同等权利
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_SalesContract_Edit,
                FunctionPermissionDefinition.P_SalesContract_Audit
            ]);
        } else {
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_SalesContract_Audit
            ]);
        }
    }

    /**
 * Check if user has read permission
 * @returns {boolean} 
 */
    static hasMetalOrderReadPermission() {
        return Engine.profile.permissionMgr.hasPermission([
            FunctionPermissionDefinition.P_MetalSalesContract_Read,
            FunctionPermissionDefinition.P_MetalSalesContract_Edit,
            FunctionPermissionDefinition.P_MetalSalesContract_Audit
        ]);
    }
    /**
 * Check if user has edit permission
 * @returns {boolean}
 */
    static hasMetalOrderEditPermission() {
        if (Engine.getOrgSettings().enableSalesRelatedOrdersQuickMode) {
            // 快捷模式下，编辑和审核同等权利
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_MetalSalesContract_Edit,
                FunctionPermissionDefinition.P_MetalSalesContract_Audit
            ]);
        } else {
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_MetalSalesContract_Edit
            ]);
        }
    }

    /**
     * Check if user has audit permission 
     * @returns {boolean}
     */
    static hasMetalOrderAuditPermission() {
        if (Engine.getOrgSettings().enableSalesRelatedOrdersQuickMode) {
            // 快捷模式下，编辑和审核同等权利
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_MetalSalesContract_Edit,
                FunctionPermissionDefinition.P_MetalSalesContract_Audit
            ]);
        } else {
            return Engine.profile.permissionMgr.hasPermission([
                FunctionPermissionDefinition.P_MetalSalesContract_Audit
            ]);
        }
    }



    /**
 * 销售合同主构造函数
 * @param {Object} params 构造参数
 */
    constructor({
        targetObject,
        wareHouse,
        commmodityList = [],
        inventory = null,
        receiveOrder = null,
        salesDate = new Date(),
        otherCost = CsFundDouble.zero(),
        discout = CsFundDouble.zero(),
        payedMount = null, // 注意该null
        quantity = CsDouble.zero(),
        totalMount = CsFundDouble.zero(),
        commodityPrice = CsFundDouble.zero(),
        receiveProgress = ProgressState.None,
        inventoryProgress = ProgressState.None,
        remainAmount = CsFundDouble.zero(),
        priceWithTax = CsFundDouble.zero(),
        smallChangeAmount = CsFundDouble.zero(),
        preReceiveOffset = null,  // 注意该null

        // super
        id = "",
        storeId = "",
        storeName = "",
        remark = "",
        operator = "",
        operatorId = "",
        docMaker = "",
        status = CommonOrderStatus.WaitReview,
        title = "",
        docCode = "",
        parentDocType = null,
        parentDocCode = "",
        parentDocTitle = "",
        sourceDocType = null,
        sourceDocCode = "",
        sourceDocTitle = "",
        recordDate = null,
        fundAccount = FundAccount.empty(),
        withoutSmallChange = false,
        discountRatio = 100,
        quickInventoryMode = null,

        // 初始化方式
        initWithCal = true,  // 是否需要计算，从后台来的数据初始化时不需要计算

        metalFundsPrice,      // = new OrderSelfDefFundData(),
        otherFundsMorePrice,  //= new OrderOtherFundData(),
        otherFundsLessPrice, // = new OrderOtherFundData(),
    } = {}) {
        super({
            id,
            title,
            docCode,
            storeId,
            storeName,
            status,
            docType: DocType.XSD,
            parentDocType,
            parentDocCode,
            parentDocTitle,
            sourceDocCode,
            sourceDocType,
            sourceDocTitle,
            recordDateTime: recordDate,
            operator,
            operatorId,
            docMaker,
            operateDateTime: salesDate,
            remark
        });

        this._targetObject = targetObject;
        this.wareHouse = wareHouse;
        this._commmodityList = commmodityList;
        this.inventory = inventory;
        this.receiveOrder = receiveOrder;
        this.receiveProgress = receiveProgress;
        this.inventoryProgress = inventoryProgress;
        this._otherCost = otherCost;
        this._discount = discout;
        this._payedMount = payedMount == null ? null : payedMount;
        this._quantity = quantity;
        this._commodityPrice = commodityPrice;
        this._totalMount = totalMount;
        this._remainAmount = remainAmount;
        this._priceWithTax = priceWithTax;
        this.fundAccount = fundAccount;
        this._withoutSmallChange = withoutSmallChange;
        this._discountRatio = new CsDouble(discountRatio, { precision: Definition.gConstDiscountRatePrecision });
        this._smallChangeAmount = smallChangeAmount;
        this._preReceiveOffset = preReceiveOffset;
        this._quickInventoryMode = quickInventoryMode !== null ? quickInventoryMode : OrderUtil.getSalesOrderInentoryHandleMethod();

        this._metalFundsPrice = metalFundsPrice ?? new OrderSelfDefFundData();
        this._otherFundsMorePrice = otherFundsMorePrice ?? new OrderOtherFundData();
        this._otherFundsLessPrice = otherFundsLessPrice ?? new OrderOtherFundData();

        // 计算价格和数量
        if (initWithCal) {
            this.calculatePriceAndQuantity();
        }

        // 如果有冲抵，则是能预收
        if (this._preReceiveOffset != null && this._preReceiveOffset != 0) {
            this._enablePreReceiveOffset = true;
        }
    }

    /**
  * 从报价单创建销售合同
  * @param {SalesQuotation} quotation
  * @returns {SalesContract}
  */
    static fromQuotationOrder(quotation) {
        const contract = new SalesContract({
            targetObject: quotation.targetObject,
            wareHouse: WareHouse.empty(),
            commmodityList: [],
            inventory: null,
            receiveOrder: null,
            salesDate: new Date(),
            otherCost: quotation.otherCost.value,
            discout: quotation.discount.value,
            id: "",
            storeId: quotation.storeId,
            storeName: quotation.storeName,
            status: CommonOrderStatus.WaitReview,
            parentDocType: quotation.docType,
            parentDocCode: quotation.docCode,
            parentDocTitle: quotation.title,
            sourceDocCode: quotation.docCode,
            sourceDocType: quotation.docType,
            sourceDocTitle: quotation.title,
            operator: Engine.profile.nickName,
            operatorId: Engine.profile.id,
            docMaker: Engine.profile.nickName,
            remark: ""
        });

        // 拷贝商品列表
        quotation.commmodityList.forEach(element => {
            contract._commmodityList.push(CommodityBatchWithTax.clone(element));
        });

        // 其余字段按 Dart 逻辑可补充
        return contract;
    }

    /**
     * 创建空销售合同
     * @param {Object} options
     * @returns {SalesContract}
     */
    static empty({
        id = null,
        operator = null,
        operatorId = null,
        storeId = null,
        storeName = null
    } = {}) {
        const contract = new SalesContract({
            //targetObject: TargetObject.empty({ objType: TargetObjectType.Unknown }),  todo
            targetObject: null,
            wareHouse: WareHouse.empty(),
            commmodityList: [],
            inventory: null,
            receiveOrder: null,
            salesDate: new Date(),
            id: id || "",
            storeId: storeId || "",
            storeName: storeName || "",
            status: CommonOrderStatus.WaitReview,
            operator: operator || "",
            operatorId: operatorId || "",
        });

        contract.wareHouse = OrderUtil.getOrderDefaultWarehouse({
            storeId: contract.storeId,
            curWarehouse: contract.wareHouse
        });

        contract.fundAccount = OrderUtil.getOrderDefaultFundAccount({
            storeId: contract.storeId,
            curFundAccount: contract.fundAccount
        });

        /* TODO: 临时取消
        contract.targetObject = OrderUtil.getOrderDefaultCustomer({
            curCustomer: contract.targetObject
        });
        */

        return contract;
    }

    /**
     * 克隆销售合同
     * @param {SalesContract} pc
     * @returns {SalesContract}
     */
    static clone(source) {

        let baseOrder = DocBase.clone(source);

        const contract = new SalesContract({
            targetObject: TargetObject.clone(source.targetObject),
            wareHouse: WareHouse.clone(source.wareHouse),
            otherCost: source._otherCost.value,
            discout: source._discount.value,
            remainAmount: source._remainAmount.value,
            payedMount: source._payedMount ? source._payedMount.value : null,
            quantity: source._quantity,
            commodityPrice: source._commodityPrice,
            totalMount: source._totalMount,
            inventory: source.inventory,
            receiveOrder: source.receiveOrder,
            priceWithTax: source._priceWithTax,
            commmodityList: [],
            receiveProgress: source.receiveProgress,
            inventoryProgress: source.inventoryProgress,
            fundAccount: source.fundAccount,
            withoutSmallChange: source._withoutSmallChange,
            discountRatio: source._discountRatio,
            smallChangeAmount: source._smallChangeAmount,
            preReceiveOffset: source._preReceiveOffset,
            quickInventoryMode: source._quickInventoryMode,

            //
            initWithCal: false,

            metalFundsPrice: source._metalFundsPrice,
            otherFundsMorePrice: source._otherFundsMorePrice,
            otherFundsLessPrice: source._otherFundsLessPrice
        });

        Object.assign(contract, baseOrder);

        // 拷贝商品列表
        source._commmodityList.forEach(element => {
            contract._commmodityList.push(CommodityBatchWithTax.clone(element));
        });


        return contract;
    }

    /**
     * 从JSON创建销售合同
     * @param {Object} json
     * @returns {SalesContract}
     */
    static fromJson(json) {

        console.log("SalesContract.fromJson", json);

        let baseOrder = DocBase.fromJson(json, DocType.XSD);

        const contract = new SalesContract({
            targetObject: TargetObject.fromJsonForOrders(json),
            wareHouse: new WareHouse({
                id: Util.jsonToString(json['storageId']),
                name: Util.jsonToString(json['storageName'])
            }),
            commmodityList: [],
            otherCost: Util.jsonToCsFundDouble(json.elsePrice, 0),
            discout: Util.jsonToCsFundDouble(json.discountPrice, 0),

            //////
            remainAmount: Util.jsonToCsFundDouble(json['receivePrice'], 0),
            payedMount: Util.jsonToCsFundDouble(json['prePrice'], 0),
            priceWithTax: CsFundDouble.zero(), // 构造函数中计算
            inventory: json["waitInoutOrder"] == null
                ? PendingInventory.empty()
                : PendingInventory.fromJson(json["waitInoutOrder"]),
            receiveOrder: json["waitReceiptOrder"] == null
                ? PendingReceiveOrder.empty()
                : PendingReceiveOrder.fromJson(json["waitReceiptOrder"],
                    { parentDocType: DocType.XSD, sourceDocType: DocType.XSD }),
            totalMount: Util.jsonToCsFundDouble(json['orderTotalAmount'], 0),
            quantity: Util.jsonToCsDouble(json['commodityQuantity'], 0),
            commodityPrice: Util.jsonToCsFundDouble(json['commodityTotalAmount'], 0),
            // 进度
            inventoryProgress: Util.jsonToPorgressState(json['waitInoutProcess'], ProgressState.None),

            // 进度
            receiveProgress: Util.jsonToPorgressState(json['waitRecepitProcess'], ProgressState.None),

            // 收款账户
            fundAccount: new FundAccount({
                id: Util.jsonToString(json['fundAccountId']),
                name: Util.jsonToString(json['fundAccountName']),
                balance: 0,
                bankName: "",
                income: 0,
                expenses: 0
            }),
            // 整单优惠
            discountRatio: Util.jsonToCsDouble(json['discountRatio'], 100, Definition.gConstDiscountRatePrecision),
            smallChangeAmount: Util.jsonToCsFundDouble(json['smallChange'], 0),
            withoutSmallChange: false,
            // 预收冲抵
            preReceiveOffset: Util.jsonToCsFundDouble(json['preReceiveOffset'], 0),
            quickInventoryMode: Util.jsonToBool(json['quickInventoryMode'], true),

            // 无需计算
            initWithCal: false,

            // 贵金属账户金额
            metalFundsPrice: OrderSelfDefFundData.fromJson(json['metalAccounts']),
            // 其他费用
            otherFundsMorePrice: OrderOtherFundData.fromJson(json['otherFeesMore']),
            otherFundsLessPrice: OrderOtherFundData.fromJson(json['otherFeesLess'])
        });

        Object.assign(contract, baseOrder);

        // 如果收款为0，设定为空
        // 这样在编辑已有单据时，可以根据 orgSetting 销售单据默认全额收款
        // enableSalesFullPayment 来进行数据填充
        // 不然数据为0后，无法自动填充
        if (contract._payedMount != null) {
            contract._payedMount = contract._payedMount.value == 0 ? null : contract._payedMount;
        }

        // 如果时零售等系统用户，在单据为未审核状态，设定_payMount 为空
        // 因为这些用户是按实际金额进行收款，设为空，会默认按该方式进行填充
        if (contract.status.code != CommonOrderStatus.Passed.code &&
            contract.targetObject.platformType ==
            TargetObjectPlatformType.TPlatformCreated) {
            contract._payedMount = null;
        }

        contract._withoutSmallChange = contract._smallChangeAmount.value != 0;
        let tax = Util.jsonToCsFundDouble(json['taxTotalAmount'], 0);
        // 反向计算 _priceWithTax
        contract._priceWithTax = tax.add(contract._commodityPrice);


        // 商品列表
        (json.details || []).forEach(item => {
            contract._commmodityList.push(CommodityBatchWithTax.fromJson(item, contract.docType));
        });

        /// 详情单据同步详情中对应进度信息
        if (contract.inventory != null &&
            !Util.isEmpty(contract.inventory.id) &&
            contract.inventoryProgress.code != contract.inventory.progressState.code) {
            contract.inventoryProgress = contract.inventory.progressState;
        }

        //console.log('salesContract from json:', contract);
        return contract;
    }
    /**
     * 转换为JSON
     * @returns {Object}
     */
    toJson() {
        const json = super.toJson();

        json.prePrice = this.payedMount.value;        
        json.details = this._commmodityList.filter(element => element.commodity != null).map(element => element.toJson());
        json.commodityTotalAmount = this._commodityPrice.value;
        json.orderTotalAmount = this._totalMount.value;
        json.discountPrice = this._discount.value;
        json.objId = this.targetObject.id;
        json.elsePrice = this._otherCost.value;
        json.receivePrice = this._remainAmount.value;
        json.storageId = this.wareHouse.id;
        json.taxTotalAmount = this.tax.value;
        json.fundAccountId = this.fundAccount.id;
        json.discountRatio = this._discountRatio.value;
        json.smallChange = this._smallChangeAmount.value;
        // 注意 preReceiveOffset 不能采用 _preReceiveOffset 因为有默认值判断
        json.preReceiveOffset = this.preReceiveOffset.value;

        // 系统用户直接出库
        json.quickInventoryMode = this._targetObject.platformType == TargetObjectPlatformType.TPlatformCreated
            ? 1
            : (this._quickInventoryMode ? 1 : 0);

        json.metalAccounts = this._metalFundsPrice.toJsonStr();
        json.otherFeesMore = this._otherFundsMorePrice.toJsonStr();
        json.otherFeesLess = this._otherFundsLessPrice.toJsonStr();

        return json;
    }
}